﻿#region Disclaimer/Info
///////////////////////////////////////////////////////////////////////////////////////////////////
// MetaCollection
// 
// MetaCollection is a system to provide a standard structure, permissions and metadata service
// for content organization.
//
// This project is hosted at Google Code at http://code.google.com/p/metacollection/
//
// This project is licensed under the BSD license.  See the License.txt file for more information.
///////////////////////////////////////////////////////////////////////////////////////////////////
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using MetaCollection.Framework.Model;
using MetaCollection.ContentService.Http;

namespace MetaCollection.ContentService.WebDav
{
	public class ResourceProperty : IResourceProperty
	{
		XName m_Name;
		string m_DataKey;
		Func<object, object> m_OutputTransform = (o) => o;
		Func<KeyValuePair<string, object>, bool> m_Selector;

		/// <summary>
		/// Initializes a new instance of the <see cref="ResourceProperty"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="valueSelector">The value selector.</param>
		public ResourceProperty(XName name)
		{
			m_Name = name;
			m_DataKey = name.LocalName.ToUpperInvariant();
			m_Selector = v => v.Key.Equals(m_DataKey, StringComparison.Ordinal);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ResourceProperty"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="dataPropertyName">Name of the data property.</param>
		public ResourceProperty(XName name, string dataPropertyName)
		{
			m_Name = name;
			m_DataKey = dataPropertyName.ToUpperInvariant();
			m_Selector = v => v.Key.Equals(m_DataKey, StringComparison.Ordinal);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ResourceProperty"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="dataPropertyName">Name of the data property.</param>
		/// <param name="outputTransform">A function to transform the data object for output in the Element value.</param>
		public ResourceProperty(XName name, string dataPropertyName, Func<object, object> outputTransform)
		{
			m_Name = name;
			m_DataKey = dataPropertyName.ToUpperInvariant();
			m_OutputTransform = outputTransform;
			m_Selector = v => v.Key.Equals(m_DataKey, StringComparison.Ordinal);
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="ResourceProperty"/> class.
		/// </summary>
		/// <param name="name">The name.</param>
		/// <param name="dataPropertyName">Name of the data property.</param>
		/// <param name="outputTransform">A function to transform the data object for output in the Element value.</param>
		/// <param name="dataSelector">The data selector.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")]
		public ResourceProperty(XName name, string dataPropertyName, Func<KeyValuePair<string, object>, bool> dataSelector, Func<object, object> outputTransform)
		{
			m_Name = name;
			m_DataKey = dataPropertyName.ToUpperInvariant();
			m_OutputTransform = outputTransform;
			m_Selector = dataSelector;
		}

		/// <summary>
		/// Gets the name of this property.
		/// </summary>
		/// <value>The name of this property.</value>
		public XName Name { get { return m_Name; } }
		/// <summary>
		/// Gets the data value selector.
		/// </summary>
		/// <value>The data value selector.</value>
		public Func<KeyValuePair<string, object>, bool> DataValueSelector { get { return m_Selector; } }
		/// <summary>
		/// Gets the name of the item property that this resource property is associated with.
		/// </summary>
		/// <value>The name of the item property.</value>
		public string ItemPropertyName { get { return m_DataKey; } }
		/// <summary>
		/// Returns an XElement that represents the property
		/// </summary>
		/// <param name="sourceItem">The source item.</param>
		/// <param name="requestType">Type of the request.</param>
		/// <returns>An XElement representing this ResourceProperty</returns>
		public XElement[] Element(IEnumerable<object> data)
		{
			if (data != null)
				return new XElement[] { new XElement(m_Name, from d in data select m_OutputTransform(d)) };
			else
				return new XElement[] { new XElement(m_Name) };
		}
	}
}
